//
//  YRNKSharedThreadPool.swift
//  YoruNeko
//
//  Created by liphone on 2021/6/17.
//

import Foundation

/**
 程序共享线程池
 */
class YRNKSharedThreadPool {
    
    /**
    程序主线程, 用来在不确定的工作线程的上下文中同步更新ui
        */

    static let mainThread = DispatchQueue.main
    
    /**
            默认队列，优先度正常
     */
    static let workThread = DispatchQueue.init(label: "yrnk_serial")
    
    static let workThreadCocurrent = DispatchQueue.init(label: "ynrk_cocurrent",qos:.userInitiated, attributes: .concurrent, autoreleaseFrequency: .never)
    
    static func dispatchTask(workTask: @escaping ()->Void){
        
    }
    
    /**
     逃逸闭包，函数闭包在传入函数后异步执行，且在函数退出后仍然存在
      
     这里的任务调度遵循FIFO 原则
     */
    static func dispatchUITask( ui_operation:@escaping ()->Void){
        mainThread.async {
            ui_operation()
        }
    }
    
    static func dispatchTask(operation: @escaping ()->Void){
        workThread.async {
            operation()
        }
    }
    
    static func dispatchUITask( task:YRNKDispatchable){
        mainThread.async{
            task.dispatch()
        }
    }
    
    static func dispatchTask(task: YRNKDispatchable){
        workThread.async {
            task.dispatch()
        }
    }
    
    static func dispatchTask(operation: @escaping ()->Void,priority:YRNKPriority){
        if priority == .NORMAL {
            workThread.async {
                operation()
            }
        }
        else if priority == .HIGH{
            workThreadCocurrent.async {
                operation()
            }
        }
    }

    
    static func dispatchTask(task:YRNKDispatchable,priority:YRNKPriority){
        if priority == .NORMAL{
            dispatchTask(task: task)
        }
        else if priority == .HIGH{
            workThreadCocurrent.async {
                task.dispatch()
            }
        }
    }
    
    
    /**
     将任务调度到组，该组可以是自定义的，不传入组就是调用默认的组，
     组的概念主要用于同步处理，可以通过组引用使得该组中的所有线程同步
     group.notify() 不阻塞
     group.wait() 阻塞
     */
    static func dispatchTaskInGroup(group:DispatchGroup,task:YRNKDispatchable){
        workThreadCocurrent.async(group: group, execute: task.dispatch)
    }
    
    static func dispatchTaskInGroup(group:DispatchGroup,operation:@escaping ()->Void){
        workThreadCocurrent.async(group: group, execute: operation)
    }
    
    /**
     将任务添加到队列中，并等待该提交任务执行完毕后返回，如果队列中已经有其他任务，将会执行完其他任务再执行此提交任务
     死锁注意： 是串行任务队列，则请勿在任务函数中执行该同步，否则将会造成死锁
     */
    static func dispatchTaskSync(task:YRNKDispatchable,priority:YRNKPriority){
        if priority == .HIGH {
            workThreadCocurrent.sync {
                task.dispatch()
            }
        }
        else if priority == .NORMAL {
            workThread.sync {
                task.dispatch()
            }
        }
    }
    
    /**
     主线程同步代码，提交的任务只有在执行完毕后才能返回
     死锁：请勿在主线程中调用该函数，否则将会造成死锁，因为主线程中调用该函数需要返回，而返回的结果必须等待任务队列中其他任务执行完毕，
     而当前提交的任务又在任务队列末尾，因此无法执行完毕，即当前执行同步的任务即在队列头部也在队列尾部。
     */
    static func dispatchUITaskSync(task:YRNKDispatchable) {
        mainThread.sync {
            task.dispatch()
        }
    }
    
    static func dispatchUITaskSync(operation: @escaping ()->Void){
        mainThread.sync {
            operation()
        }
    }
}

/**
 任务协议，需要实现一个方法,亦可以传入逃逸类型的闭包，而不使用包装类型
 */
protocol YRNKDispatchable {
    func dispatch()
}

enum YRNKPriority{
    case HIGH, NORMAL
}
